package com.qidian.mes.sys.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qidian.common.pojo.MESResult;
import com.qidian.common.util.Constant;
import com.qidian.common.util.JSONTools;
import com.qidian.common.util.ThreadPoolUtil;
import com.qidian.mes.pojo.Dict;
import com.qidian.mes.sys.mapper.DictMapper;
import com.qidian.mes.sys.service.DictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Author 戴着假发的程序员
 * @Company 起点编程
 * @Description
 * @Time 2024/10/12 上午 10:41
 */
@Service
public class DictServiceImpl implements DictService {
    @Autowired
    private DictMapper dictMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Value("${dict-cache-pre:DICT_}")
    private String dictCachePre;
    // 清理字典缓存的线程池的名字
    @Value("${dict-cache-clear-thread-pool-name:dictCacheClearThreadPoolName")
    private String dictCacheClearThreadPoolName;
    @Override
    public MESResult queryDictAndDataByType(String dictType) {
        return MESResult.success(queryDictFromRedisOrMySQL(dictType));
    }
    @Override
    public MESResult queryDictAndDataByTypes(String [] dictType) {
        List<Dict> dicts = new ArrayList<>();
        Arrays.stream(dictType).forEach(type->dicts.add(queryDictFromRedisOrMySQL(type)));
        return MESResult.success(dicts);
    }
    //  自定义方法根据类别查询缓存
    private Dict queryDictFromRedisOrMySQL(String dictType){
        // 查询缓存
        String key = dictCachePre + dictType;
        if(stringRedisTemplate.hasKey(key)){
            String dictJson = stringRedisTemplate.opsForValue().get(key);
            try {
                Dict dict = JSONTools.json2object(dictJson,Dict.class);
                return dict;
            } catch (Exception e) {
                // 清空缓存
                stringRedisTemplate.delete(key);
            }
        }
        // 缓存没有数据,查询数据库
        Dict dict = dictMapper.selectDictAndDataByType(dictType);
        // 保存缓存
        stringRedisTemplate.opsForValue().set(key,JSONTools.object2json(dict));
        // 设置缓存的时间
        stringRedisTemplate.expire(key,30 + new Random().nextInt(30), TimeUnit.MINUTES);
        return dict;
    }

    @Override
    public MESResult save(Dict dict) {
        // 查重
        Dict tempDict = dictMapper.selectByName(dict.getDictName());
        if(tempDict != null)
            return MESResult.error(Constant.RESPONSE_STATUS_REPEAT,"字典名称重复");
        if(dictMapper.selectByType(dict.getDictType()) != null)
            return MESResult.error(Constant.RESPONSE_STATUS_REPEAT,"字典类型重复");
        return MESResult.isSuccess(dictMapper.insert(dict));
    }

    @Override
    public MESResult list(Dict dict, int page, int limit) {
        PageHelper.startPage(page,limit);
        // 查询数据
        List<Dict> dicts = dictMapper.selectList(dict);
        return MESResult.success(new PageInfo<Dict>(dicts));
    }

    @Override
    public MESResult get(Long dictId) {
        return MESResult.success(dictMapper.selectById(dictId));
    }

    @Override
    public MESResult update(Dict dict) {
        // 查重
        Dict tempDict = dictMapper.selectByName(dict.getDictName());
        if(tempDict != null && !tempDict.getDictId().equals(dict.getDictId()))
            return MESResult.error(Constant.RESPONSE_STATUS_REPEAT,"字典名称重复");
        tempDict = dictMapper.selectByType(dict.getDictType());
        if(tempDict != null && !tempDict.getDictId().equals(dict.getDictId()))
            return MESResult.error(Constant.RESPONSE_STATUS_REPEAT,"字典类型重复");
        int result = dictMapper.updateById(dict);
        // 处理缓存
        String key = dictCachePre + dict.getDictType();
        if(stringRedisTemplate.hasKey(key)){
            // 清理缓存
            stringRedisTemplate.delete(key);
            // 子线程再次删除
            ExecutorService threadPool = ThreadPoolUtil.getThreadPool(dictCacheClearThreadPoolName);
            threadPool.submit(()->{
                int count = 0;
                while ( ++count < 10){
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    if(stringRedisTemplate.delete(key)){
                        break;
                    }
                }
                if(count == 10){
                    throw new RuntimeException("清理缓存失败，缓存的key为： " + key);
                }
            });
        }
        return MESResult.isSuccess(result);
    }

    @Override
    public MESResult delete(Long dictId) {
        Dict dict = dictMapper.selectById(dictId);
        if(dict == null){
            return MESResult.success();
        }
        int i = dictMapper.deleteById(dictId);
        // 处理缓存
        String key = dictCachePre + dict.getDictType();
        if(stringRedisTemplate.hasKey(key)){
            // 清理缓存
            stringRedisTemplate.delete(key);
            // 子线程再次删除
            ExecutorService threadPool = ThreadPoolUtil.getThreadPool(dictCacheClearThreadPoolName);
            threadPool.submit(()->{
                int count = 0;
                while ( ++count < 10){
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    if(stringRedisTemplate.delete(key)){
                        break;
                    }
                }
                if(count == 10){
                    throw new RuntimeException("清理缓存失败，缓存的key为： " + key);
                }
            });
        }
        return MESResult.success();
    }

    @Override
    public MESResult deletes(Long[] dictIds) {
        return MESResult.success(dictMapper.deletesById(dictIds));
    }


}
